package com.woniuxy.moneyapp.app.controller;


import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.config.AlipayConfig;
import com.woniuxy.commons.exception.MyException;
import com.woniuxy.commons.util.*;

import com.woniuxy.moneyapp.app.controller.form.RechargeStateInfo;
import com.woniuxy.moneyapp.client.RechargeRecordClient;
import com.woniuxy.moneyapp.client.param.CashAmount;
import com.woniuxy.moneyapp.common.enums.PaymentRelated;
import com.woniuxy.moneyapp.common.enums.SchemaCode;
import com.woniuxy.moneyapp.common.exception.code.FundExceptionCode;
import com.woniuxy.moneyapp.common.utils.CommonUtil;
import com.woniuxy.moneyapp.infra.model.PayRecord;
import com.woniuxy.moneyapp.infra.model.RechargeRecord;
import com.woniuxy.moneyapp.service.CashRecordService;
import com.woniuxy.moneyapp.service.PayRecordService;
import com.woniuxy.moneyapp.service.RechargeRecordService;

import com.woniuxy.userapp.client.FrontAccountClient;
import com.woniuxy.userapp.client.param.RechargeInfo;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.ApiOperation;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.hibernate.validator.constraints.pl.REGON;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author seven
 * @since 2022-08-01
 */
@RestController
public class RechargeRecordController implements RechargeRecordClient {
    @Resource
    private RechargeRecordService rechargeRecordService;

    @Resource
    private PayRecordService payRecordService;

    @Resource
    private RocketMQTemplate rt;

    @Resource
    private FrontAccountClient fac;

    @Resource
    private CashRecordService cashRecordService;

    @Resource
    private StringRedisTemplate srt;


    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void pay(@RequestParam String cashAmount111) throws IOException {
        //相同订单重复发起支付请求
        //根据token 查用户id 用户名
        LoginUserDto userDto = GetTokenUserLogin.getTokenUserLogin();
        System.out.println(userDto);
        //前台帐户id
        Integer uid = userDto.getLoginId();
        //前台帐户用户名
        String uName = userDto.getLoginName();
        //参数验证
        if(cashAmount111==null)
            throw new MyException
                    (FundExceptionCode.PARAM_NULL.getCode(),
                            FundExceptionCode.PARAM_NULL.getMsg());
        if(Long.parseLong(cashAmount111)<=0)
            throw new MyException
                    (FundExceptionCode.CASH_AMOUNT_ERROR.getCode(),
                            FundExceptionCode.CASH_AMOUNT_ERROR.getMsg());
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        String out_trade_no = CommonUtil.getRechargeCode(SchemaCode.RECHARGE_CODE.getNum());
        String merchant_order_no = CommonUtil.getRechargeCode(SchemaCode.SERIAL_CODE.getNum());


        //订单名称，必填
        String subject = PaymentRelated.ALIPAY_NAME.getDesc()+"";
        BigDecimal cashAmount = new BigDecimal(cashAmount111);
        BigDecimal amount = new BigDecimal(cashAmount111);

        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setCashAmount(amount);
        rechargeRecord.setRechargeNum(out_trade_no);
        rechargeRecord.setPayment(PaymentRelated.ALIPAY_NAME.getDesc());
        rechargeRecord.setUserId(uid);
        rechargeRecord.setState(0);
        rechargeRecord.setScence(SchemaCode.RECHARGE_CODE.getNum());
        rechargeRecordService.save(rechargeRecord);

        //商品描述，可空
        String body = uid+":"+uName+":"+merchant_order_no+":"+rechargeRecord.getId();//用户名写这
        System.out.println(body);
        PayRecord payRecord = new PayRecord();
        payRecord.setScence(SchemaCode.RECHARGE_CODE.getNum());
        payRecord.setPaymentWay(PaymentRelated.ALIPAY_NAME.getDesc());
        payRecord.setCashAmount(amount);
        payRecord.setState(0);
        payRecord.setPayNum(merchant_order_no);
        payRecord.setOrderNum(out_trade_no);
        if(!payRecordService.save(payRecord))
            throw new MyException(FundExceptionCode.DAO_ERROR.getCode(),FundExceptionCode.DAO_ERROR.getMsg());

        alipayRequest.setBizContent("{\"out_trade_no\":\""+out_trade_no+"\","
                + "\"total_amount\":\""+cashAmount+"\","
                + "\"subject\":\""+subject+"\","
                + "\"body\":\""+body+"\","
                + "\"merchant_order_no\":\""+merchant_order_no+"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");


        //请求
        String result = null;
        try {
            result = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        System.out.println(("即将进入支付宝============================"));
        //输出
        HttpServletResponse response = WebUtil.getResponse();
        response.getWriter().println(result);
    }

    @ApiOperation("支付宝充钱异步回调")
    @PostMapping("/rechargeRecord/addinfo")
   public void service(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(("支付宝充钱异步回调"));
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
          /*  valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);*/
            params.put(name, valueStr);
        }

        boolean signVerified = false; //调用SDK验证签名
        try {
            signVerified = AlipaySignature.rsaCheckV1(params, com.alipay.config.AlipayConfig.alipay_public_key, com.alipay.config.AlipayConfig.charset, com.alipay.config.AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        //——请在这里编写您的程序（以下代码仅作参考）——

	/* 实际验证过程建议商户务必添加以下校验：
	1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
	2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
	3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
	4、验证app_id是否为该商户本身。
	*/
        if(signVerified) {//验证成功
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

            //body
            String body = new String(request.getParameter("body").getBytes("ISO-8859-1"),"UTF-8");
            System.out.println(body);

            //total_amount
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
            System.out.println(total_amount);
            if(trade_status.equals("TRADE_FINISHED")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            }else if (trade_status.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序
                //注意：
                //付款完成后，支付宝系统发送该交易状态通知
                String[] split = body.split(":");
                Integer uid = Integer.parseInt(split[0]);
                String uName = split[1];
                String merchant_order_no = split[2];
                Integer rid = Integer.parseInt(split[3]);
                System.out.println(split);
                RechargeInfo rechargeInfo = new RechargeInfo();
                rechargeInfo.setAccountId(uid);
                rechargeInfo.setAmount(new BigDecimal(total_amount));
                Result recharge = fac.recharge(rechargeInfo);
                if(recharge.getCode()!=200)
                    throw new MyException(FundExceptionCode.RECHARGE_ACC_FAIL.getCode(),FundExceptionCode.RECHARGE_ACC_FAIL.getMsg());
                RechargeStateInfo rechargeStateInfo = new RechargeStateInfo();
                rechargeStateInfo.setSericalNum(merchant_order_no);
                rechargeStateInfo.setOut_trade_no(out_trade_no);
                rechargeStateInfo.setPayerName(uName);
                rechargeStateInfo.setPayerId(uid);
                rechargeStateInfo.setScenceId(rid);
                rechargeStateInfo.setCashAmount(new BigDecimal(total_amount));

                Message<RechargeStateInfo> msg = MessageBuilder.withPayload(rechargeStateInfo).build();
                rt.asyncSend("post_recharge_related_info",msg,
                        new SendCallback() {
                            @Override
                            public void onSuccess(SendResult sendResult) {
                                System.out.println("发送成功: " + sendResult);
                            }

                            @Override
                            public void onException(Throwable e) {
                                System.out.println("发送失败: " + e.getMessage());
                            }
                        });
            }



        }else {//验证失败
            resp.getWriter().println("fail");

            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
            //AlipayConfig.logResult(sWord);
        }

        //——请在这里编写您的程序（以上代码仅作参考）——
    }



}

